package com.trust.walletcore.example


import android.os.Bundle
import android.util.Log
import android.widget.LinearLayout
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import com.google.protobuf.ByteString
import com.trust.walletcore.example.utils.SolanaTransactionSender
import com.trust.walletcore.example.utils.SolanaTransactionSender.getSolBalance
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import wallet.core.java.AnySigner

import wallet.core.jni.BitcoinScript
import wallet.core.jni.BitcoinSigHashType
import wallet.core.jni.CoinType
import wallet.core.jni.HDWallet
import wallet.core.jni.PrivateKey
import wallet.core.jni.PublicKey
import wallet.core.jni.proto.Bitcoin
import wallet.core.jni.proto.Common
import wallet.core.jni.proto.Ethereum
import wallet.core.jni.proto.Solana
import java.math.BigInteger
import kotlin.experimental.and


class MainActivity : AppCompatActivity() {

    var logView: LinearLayout? = null

    var publicKeySolana: PublicKey? = null

    var address = ""
    var publicKeyStr = ""


    init {
        System.loadLibrary("TrustWalletCore")
    }

    private val seedPhrase =
        "morning injury furnace juice among refuse evil liquid stairs fold change vapor"
    private val passphrase = ""//密码


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        logView = findViewById<LinearLayout>(R.id.logView)

        // 1. 创建一个新的助记词
        val mnemonic = HDWallet(128, "") // 128位熵，创建新的助记词
//        showLog("创建一个新的助记词: ${mnemonic.mnemonic()}")

        // 'Import' a wallet
        val wallet = HDWallet(seedPhrase, passphrase)
        showLog("\n 现用的Mnemonic: \n${wallet.mnemonic()}\n")


        address = wallet.getAddressForCoin(CoinType.SOLANA)
        showLog("Solana钱包地址: \n$address\n")


        runBlocking {
            launch(Dispatchers.IO) {
                val solBalance = getSolBalance(address)

                showLog(address + "钱包余额: $solBalance SOL")
            }
        }

        SolanaFaucet.requestFaucet(address)

        var privateKeySolana = wallet.getKeyForCoin(CoinType.SOLANA)


        var privateKeyStr=privateKeySolana.data().toHexString(false)

        showLog("0.Solana.privateKey: \n$privateKeyStr\n")

        // 将十六进制私钥字符串转换为字节数组
        val privateKeyBytes = privateKeyStr.hexStringToByteArray()

// 创建 PrivateKey 对象
        val privateKey = PrivateKey(privateKeyBytes)

// 获取对应的公钥
        val publicKey = privateKey.publicKeyEd25519

// 获取对应的 Solana 地址
        val address = CoinType.SOLANA.deriveAddress(privateKeySolana)

        showLog("只有私钥: $privateKeyStr")
        showLog("私钥-》公钥: ${publicKey.data().toHexString()}")
        showLog("私钥-》地址: $address")


        publicKeySolana = privateKeySolana.publicKeyEd25519
        showLog("Solana.publicKey: \n${publicKeySolana?.data()?.toHexString()}")
        // 4. 转换为地址格式
        val address1 = CoinType.SOLANA.deriveAddress(privateKeySolana)
        showLog("Solana钱包地址(私钥生成): \n$address1\n")


        // 在协程作用域内调用 getRecentBlockhash
        runBlocking {
            launch(Dispatchers.IO) {

                val transactionSignatures =
                    SolanaTransactionSender.getTransactionSignatures(address)

                if (transactionSignatures != null) {
                    println("Solana Transaction Signatures:")
                    transactionSignatures.forEach { println("Solana 签名记录：$it") }
                } else {
                    println("Solana 签名记录 Failed to fetch transaction signatures.")
                }

                val blockhash = SolanaTransactionSender.getRecentBlockhash()
                //{jsonrpc=2.0, result={context={apiVersion=2.1.8, slot=3.56740911E8},
                // value={blockhash=AFEx3z3BYNiHWXu37tbgMQU9Lzmbd87EkT4ExvXSfu5n, lastValidBlockHeight=3.44789943E8}}, id=1.0}
                Log.d("logcat", "Solana 获取最近的区块哈希: $blockhash")

                testTransferSOL(privateKeySolana, blockhash)
                // 在这里处理 blockhash，例如更新 UI
                runOnUiThread {
                    // 更新 UI 的代码
                }
            }
        }


        //  testSol()


        // Ethereum example
        // ethereumExample(wallet)

        // BitcoinExample(wallet)


    }


    /*
      交易签名(Transaction Signing using Sol)
    */
    private fun testSignedTransaction(privateKeySolana: PrivateKey, blockhash: String) {

        //设定一个接收地址
        val dummyReceiverAddress =
            "6zMNYYnqdVorfvmPHQNKz9D33iDeWahVHbdoKFTPc8xY"//"2RDc2DkFMqtdC3UCGbZeV9fieo9XA1DvyVPCdmEtbjCJ"
        // 假设这些变量已经定义 your_recent_blockhash_here
        //   val blockhash = "your_recent_blockhash_here"
        val amount = 1L;//BigInteger.valueOf(1000000) // 转账金额（1 SOL = 10^9 Lamports）

        //构建交易消息 注意：实际需要更复杂的指令序列化，此处为简化示例
        val transferMessage = Solana.Transfer.newBuilder().apply {
            recipient = dummyReceiverAddress
            value = amount

        }.build()

        /**
         * 这里应该还有一些参数要传递，blockhash，privateKey等
         */
        val signerInput = Solana.SigningInput.newBuilder().apply {
            this.recentBlockhash = blockhash
            this.transferTransaction = transferMessage

            this.privateKey = ByteString.copyFrom(privateKeySolana.data())
        }.build()
        val signerOutput =
            AnySigner.sign(signerInput, CoinType.SOLANA, Solana.SigningOutput.parser())
        showLog(
            "Solana 签名交易 Signed transaction: \n${
                signerOutput.encoded.toByteArray().toHexString(false)
            }"
        )

        runBlocking {
            launch(Dispatchers.IO) {
                SolanaTransactionSender.sendTransaction(
                    signerOutput.encoded
                )
            }
        }


    }

    /**
     * 转账sol
     */
    private fun testTransferSOL(privateKeySolana: PrivateKey, blockhash: String) {

        publicKeyStr = privateKeySolana.data().toHexString(false)
        showLog("Solana.privateKey: \n$publicKeyStr")


        //设定一个接收地址
        val dummyReceiverAddress =
            "EN2sCsJ1WDV8UFqsiTXHcUPUxQ4juE71eCknHYYMifkd"//"2RDc2DkFMqtdC3UCGbZeV9fieo9XA1DvyVPCdmEtbjCJ"
        val amountSol = 0.1 //0.1 个SOL
        val amountLamports = (amountSol * 1_000_000_000).toLong()


        val feePayer = address

        showLog("私钥长度必须是32 length: ${privateKeySolana.data().size}")

        //构建交易消息 注意：实际需要更复杂的指令序列化，此处为简化示例
        val transferMessage = Solana.Transfer.newBuilder().apply {
            recipient = dummyReceiverAddress
            value = amountLamports

        }.build()

        /**
         * 这里应该还有一些参数要传递，blockhash，privateKey等
         */
        val signerInput = Solana.SigningInput.newBuilder().apply {
          recentBlockhash = blockhash
           transferTransaction = transferMessage
            //  this.feePayer = feePayer
            // this.rawMessage =Solana.RawMessage.newBuilder().set.build()
              this.privateKey = ByteString.copyFrom(privateKeySolana.data())


        }.build()
        val signerOutput =
            AnySigner.sign(signerInput, CoinType.SOLANA, Solana.SigningOutput.parser())
        showLog(
            "转账sol 签名: \n${
                signerOutput.encoded
            }"
        )

        runBlocking {
            launch(Dispatchers.IO) {
                val transactionHash = SolanaTransactionSender.sendTransaction(
                    signerOutput.encoded//.toByteArray()
                )
                //  // {"jsonrpc":"2.0","result":"3msVairSThpvQZu4HPkHUBt79eSS8k9S1BFyehGeABZJm66twakKToYj584YyPnoSWN2CxbxzEgA6fQ6p3eBWMqN","id":1}
                showLog("hash: $transactionHash")
            }
        }


    }

    private fun ethereumExample(wallet: HDWallet) {
        val coinEth: CoinType = CoinType.ETHEREUM
        // Get the default address
        val addressEth = wallet.getAddressForCoin(coinEth)
        showLog("\n eth钱包地址: \n$addressEth")

        // Signing a transaction (using EthereumSigner)
        val secretPrivateKey = wallet.getKeyForCoin(coinEth)
        val dummyReceiverAddress = "0xC37054b3b48C3317082E7ba872d7753D13da4986"

        val signerInput = Ethereum.SigningInput.newBuilder().apply {
            this.chainId = ByteString.copyFrom(BigInteger("01").toByteArray())
            this.gasPrice = BigInteger("d693a400", 16).toByteString() // decimal 3600000000
            this.gasLimit = BigInteger("5208", 16).toByteString()     // decimal 21000
            this.toAddress = dummyReceiverAddress
            this.transaction = Ethereum.Transaction.newBuilder().apply {
                this.transfer = Ethereum.Transaction.Transfer.newBuilder().apply {
                    this.amount = BigInteger("0348bca5a16000", 16).toByteString()
                }.build()
            }.build()
            this.privateKey = ByteString.copyFrom(secretPrivateKey.data())
        }.build()
        val signerOutput =
            AnySigner.sign(signerInput, CoinType.ETHEREUM, Ethereum.SigningOutput.parser())
        showLog("Signed transaction: \n${signerOutput.encoded.toByteArray().toHexString(false)}")
    }

    private fun testSol() {
        val senderAddress = "your_sender_address"
        val receiverAddress = "your_receiver_address"
        val amount: Long = 1000000 // lamports
        val recentBlockhash = "从RPC获取的区块哈希"


    }


    /**
     * 构建 Solana 转账交易的序列化消息（核心步骤）
     */
    fun buildSolanaTransferMessage(
        sender: String,
        receiver: String,
        lamports: Long,
        recentBlockhash: String
    ): ByteArray {
        // 使用第三方库（如 solana-kotlin）简化构建，此处为手动序列化示例
        // 注意：实际开发请使用官方推荐的库（如 solana-web3.js 或 solana-kotlin）
        return Solana.Transfer.newBuilder()
            //.setSender(sender)
            // .setReceiver(receiver)
            //  .setAmount(lamports)
            // .setRecentBlockhash(recentBlockhash)
            .build()
            .toByteArray()
    }


    // 待验证 使用 TrustWalletCore 签名交易（无需 MWA）
    fun signWithLocalKey(transaction: ByteArray, privateKey: ByteArray): ByteArray {
        val signingInput = Solana.SigningInput.newBuilder().apply {
            this.privateKey = ByteString.copyFrom(privateKey)
//            this.transferTransaction = transaction
        }.build()
        val signingOutput =
            AnySigner.sign(signingInput, CoinType.SOLANA, Solana.SigningOutput.parser())
        return signingOutput.encoded.toByteArray()
    }

    /**
     * 比特币测试
     */
    private fun BitcoinExample(wallet: HDWallet) {
        // Bitcoin example
        val coinBtc: CoinType = CoinType.BITCOIN
        // Get the default address
        val addressBtc = wallet.getAddressForCoin(coinBtc)
        showLog("Default BTC address: \n$addressBtc")

        // Build a transaction
        val utxoTxId =
            "050d00e2e18ef13969606f1ceee290d3f49bd940684ce39898159352952b8ce2".hexStringToByteArray();
        val secretPrivateKeyBtc = wallet.getKeyForCoin(coinBtc)
        val toAddress = "1Bp9U1ogV3A14FMvKbRJms7ctyso4Z4Tcx"
        val changeAddress = "1FQc5LdgGHMHEN9nwkjmz6tWkxhPpxBvBU"
        val script = BitcoinScript.lockScriptForAddress(addressBtc, coinBtc).data()

        val outPoint = Bitcoin.OutPoint.newBuilder().apply {
            this.hash = ByteString.copyFrom(utxoTxId)
            this.index = 2
        }.build()
        val utxo = Bitcoin.UnspentTransaction.newBuilder().apply {
            this.amount = 5151
            this.outPoint = outPoint
            this.script = ByteString.copyFrom(script)
        }.build()
        val input = Bitcoin.SigningInput.newBuilder().apply {
            this.amount = 600
            this.hashType = BitcoinSigHashType.ALL.value()
            this.toAddress = toAddress
            this.changeAddress = changeAddress
            this.byteFee = 2
            this.coinType = coinBtc.value()
            this.addUtxo(utxo)
            this.addPrivateKey(ByteString.copyFrom(secretPrivateKeyBtc.data()))
        }

        // Calculate fee (plan a tranaction)
        val plan = AnySigner.plan(input.build(), coinBtc, Bitcoin.TransactionPlan.parser())
        showLog("Planned fee:  ${plan.fee}  amount: ${plan.amount}  avail_amount: ${plan.availableAmount}  change: ${plan.change}")

        // Set the precomputed plan
        input.plan = plan
        input.amount = plan.amount

        val output = AnySigner.sign(input.build(), coinBtc, Bitcoin.SigningOutput.parser())

        assert(output.error == Common.SigningError.OK)
        val signedTransaction = output.encoded?.toByteArray()
        showLog("Signed BTC transaction: \n${signedTransaction?.toHexString()}")
    }

    private fun ByteArray.toHexString(withPrefix: Boolean = true): String {
        val stringBuilder = StringBuilder()
        if (withPrefix) {
            stringBuilder.append("0x")
        }
        for (element in this) {
            stringBuilder.append(String.format("%02x", element and 0xFF.toByte()))
        }
        return stringBuilder.toString()
    }

    private fun BigInteger.toByteString(): ByteString {
        return ByteString.copyFrom(this.toByteArray())
    }

    private fun String.hexStringToByteArray(): ByteArray {
        val HEX_CHARS = "0123456789ABCDEF"
        val result = ByteArray(length / 2)
        for (i in 0 until length step 2) {
            val firstIndex = HEX_CHARS.indexOf(this[i].toUpperCase());
            val secondIndex = HEX_CHARS.indexOf(this[i + 1].toUpperCase());
            val octet = firstIndex.shl(4).or(secondIndex)
            result.set(i.shr(1), octet.toByte())
        }
        return result
    }

    private fun showLog(log: String) {
        Log.i("logcat", log)
        val tv = TextView(this)
        tv.text = log
        logView?.addView(tv)

    }
}
